package net.grandcentrix.thirtyinch.sample.fragmentlifecycle;

import net.grandcentrix.thirtyinch.sample.ResourceTable;
import net.grandcentrix.thirtyinch.TiLog;
import net.grandcentrix.thirtyinch.sample.util.DeveloperOptions;
import ohos.aafwk.ability.fraction.Fraction;
import ohos.aafwk.ability.fraction.FractionAbility;
import ohos.aafwk.ability.fraction.FractionManager;
import ohos.aafwk.ability.fraction.FractionScheduler;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.Switch;
import ohos.agp.components.Text;
import ohos.agp.window.dialog.ToastDialog;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import rx.Observable;

import java.util.Optional;
import java.util.concurrent.TimeUnit;

public class FragmentLifecycleActivity extends FractionAbility {

    private String TAG = this.getClass().getSimpleName() + "@" + Integer.toHexString(this.hashCode());

    private Switch switchAddToBackStack = null;

    private Switch switchRetainPresenterInstance = null;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
//        if (savedInstanceState == null) {
        //started for the first time, reset all counters
        fragmentLifecycleActivityInstanceCount = -1;
        TestFragment.testFragmentInstanceCount = -1;
//        }

        fragmentLifecycleActivityInstanceCount++;
        setUIContent(ResourceTable.Layout_activity_fragment_lifecycle);
//        FractionManager.enableDebugLogging(true);
        TiLog.v(TAG, "onStart of " + this);

        switchAddToBackStack = (Switch) findComponentById(ResourceTable.Id_switch_add_back_stack);
        switchRetainPresenterInstance = (Switch) findComponentById(ResourceTable.Id_switch_retain_presenter_instance);
        findComponentById(ResourceTable.Id_recreateActivity).setEnabled(false);
//        findComponentById(ResourceTable.Id_recreateActivity).setClickedListener(v -> recreateActivity(v));
        findComponentById(ResourceTable.Id_finishActivity).setClickedListener(v -> finishActivity(v));
        findComponentById(ResourceTable.Id_addFragmentB).setClickedListener(v -> addFragmentB(v));
        findComponentById(ResourceTable.Id_addFragmentA).setClickedListener(v -> addFragmentA(v));
        findComponentById(ResourceTable.Id_removeFragmentA).setClickedListener(v -> removeFragmentA(v));


        findComponentById(ResourceTable.Id_detachFragmentAndAddAgain).setClickedListener(v -> detachFragmentAndAddAgain(v));
        Text textDontKeepActivities = (Text) findComponentById(ResourceTable.Id_text_dont_keep_activities);
        int keepActivitiesText = DeveloperOptions.isDontKeepActivitiesEnabled() ?
                ResourceTable.String_dont_keep_activities_enabled
                :
                ResourceTable.String_dont_keep_activities_disabled;
        textDontKeepActivities.setText(keepActivitiesText);

        TiLog.v(TAG, "// A new Activity gets created by the Android Framework.");
        TiLog.v(TAG, "final HostingActivity hostingActivity" + fragmentLifecycleActivityInstanceCount
                + " = new HostingActivity();");
    }

    @Override
    public void onInactive() {
        super.onInactive();
        TiLog.d(TAG, "onInactive()");
    }

//    @Override
//    fun onSaveInstanceState(outState: Bundle) {
//        super.onSaveInstanceState(outState)
//        TiLog.d(TAG, "onSaveInstanceState(Bundle)")
//    }

    @Override
    public void onStop() {
        super.onStop();

        TiLog.v(TAG, "onStop");

        TiLog.v(TAG, "// hostingActivity" + fragmentLifecycleActivityInstanceCount
                + " got destroyed.");
    }

    void addFragmentA(Component view) {
        TestFragmentA fragment = new TestFragmentA();
        TiLog.v(TAG, "adding FragmentA");
        addFragment(fragment);
    }

    void addFragmentB(Component view) {
        TestFragmentB fragment = new TestFragmentB();
        TiLog.v(TAG, "adding FragmentB");
        addFragment(fragment);
    }

    void detachFragmentAndAddAgain(Component view) {
        FractionManager supportFragmentManager = getFractionManager();
        Optional<Fraction> fragmentOp = supportFragmentManager.getFractionByTag("fragment_placeholder");

        if (fragmentOp.isPresent()) {
            Fraction fragment = fragmentOp.get();
            //remove fragment
            TiLog.v(TAG, "// When the Fragment is removed.");
            supportFragmentManager.startFractionScheduler().remove(fragment).submit();

            TiLog.v(TAG, "// When the Fragment get added again to the Activity.");
            //add after delay again. Don't use the same transaction
            Observable.just(null).delay(1, TimeUnit.SECONDS)
                    .subscribe(n -> new EventHandler(EventRunner.getMainEventRunner()).postTask(() -> addFragment(fragment)));
        } else {
//            Toast.makeText(this, "no fragment found", Toast.LENGTH_SHORT).show();
            new ToastDialog(getContext()).setText("no fragment found").show();
        }
    }

    @Override
    public void onBackground() {
        super.onBackground();
        TiLog.v(TAG, "// When the Activity gets finished");
    }

    void finishActivity(Component view) {
        TiLog.v(TAG, "finishing Activity");
        terminateAbility();

    }

    @Override
    public void onBackPressed() {
        TiLog.v(TAG, "// When the back button gets pressed");
        FractionManager fragmentManager = getFractionManager();
        if (fragmentManager.getFractionByTag("fragment_placeholder").isPresent()) {
            TiLog.v(TAG, "// When the top most fragment gets popped");
            fragmentManager.popFromStack();
        } else {
            super.onBackPressed();
        }
    }

    void recreateActivity(Component view) {
        TiLog.v(TAG, "// And when the Activity is changing its configurations.");
//        recreate();
        //XXX: check recreate 是否ok
        Intent intent = new Intent();
        intent.setOperation(new Intent.OperationBuilder()
                .withDeviceId("")
                .withBundleName("net.grandcentrix.thirtyinch.sample")
                .withAbilityName("net.grandcentrix.thirtyinch.sample.fragmentlifecycle.FragmentLifecycleActivity")
                .build());
        startAbility(intent);
        terminateAbility(); // 没有更好的办法模拟recreate， 当前
    }

    void removeFragmentA(Component view) {
        FractionManager supportFragmentManager = getFractionManager();
        Optional<Fraction> fragment = supportFragmentManager.getFractionByTag("fragment_placeholder");
        if (fragment.isPresent()) {
            if (TestFragmentA.class.isInstance(fragment.get())) {
                TiLog.v(TAG, "remove FragmentA");
                supportFragmentManager.startFractionScheduler()
                        .remove(fragment.get())
                        .submit();
            }
        }

    }

    private void addFragment(Fraction fragment) {
        FractionManager fragmentManager = getFractionManager();
        FractionScheduler fragmentTransaction = fragmentManager.startFractionScheduler();
        boolean retain = switchRetainPresenterInstance != null ? (switchRetainPresenterInstance.isChecked() == true) : false;
        if (retain) {
            TiLog.v(TAG, "retaining presenter");
        }
        //XXX fragment.arguments?
//        if (fragment.arguments == null) {
//            val bundle = Bundle();
//            bundle.putBoolean(TestFragment.RETAIN_PRESENTER, retain);
//            fragment.arguments = bundle;
//        } else {
//            TiLog.v(TAG, "reusing fragment, not setting new arguments");
//        }

//        fragmentTransaction.replace(ResourceTable.Id_fragment_placeholder, fragment);
        Optional<Fraction> oldFraction = fragmentManager.getFractionByTag("fragment_placeholder");
        if (oldFraction.isPresent()) {
            fragmentTransaction.remove(oldFraction.get());
        }
        fragmentTransaction.add(ResourceTable.Id_fragment_placeholder, fragment, "fragment_placeholder");

        if (switchAddToBackStack != null ? switchAddToBackStack.isChecked() : false) {
            TiLog.v(TAG, "adding transaction to the back stack");
//            fragmentTransaction.addToBackStack(null); TODO: 看是否正确
            fragmentTransaction.pushIntoStack(null);
        }
        int backStackId = fragmentTransaction.submit();
        if (backStackId >= 0) {
            TiLog.v(TAG, "Back stack ID: " + backStackId);
        }
    }

    static int fragmentLifecycleActivityInstanceCount = -1;

}
